#include "clientHandler.h"
#include "addcontact.h"

using namespace std;

QString authorization = "Auth";
QString registration = "Regs";
QString message = "Msg";
QString groupMessage = "Gmsg";
QString roster = "Rstr";
QString budPresence = "BudPr";
QString presence = "Prsnc";
QString addContact = "AdC";
QString removeContact = "RmC";


ClientHandler *ClientHandler::instance_p = NULL;

ClientHandler *ClientHandler::clientHandlerInstance()
{
    if(!instance_p)
        instance_p = new ClientHandler;
    return instance_p;
}

ClientHandler::ClientHandler()
{
    // does nothing
}

void ClientHandler::setClientSocket(QTcpSocket *clientSocket)
{
    mySocket = clientSocket;
    connect(mySocket, SIGNAL(readyRead()), this, SLOT(handleIncomingData()));
    connect(mySocket, SIGNAL(disconnected()), this, SLOT(handleDisconnection()));
}

void ClientHandler::handleDisconnection()
{
    qDebug() << "Disconnected: " << mySocket->peerAddress() << ":" << mySocket->peerPort() << endl << flush;
    mySocket->close();
    this->deleteLater();
}

void ClientHandler::setUsername(QString username)
{
    this->username = username;
}


void ClientHandler::setPassword(QString password)
{
    this->password = password;
}

void ClientHandler::setFrom(QString from)
{
    this->from = from;
}

void ClientHandler::setEmail(QString email)
{
    this->email = email;
}

void ClientHandler::setScreenName (QString screenName)
{
    this->screenName = screenName;
}

void ClientHandler::setTo(QString to)
{
    this->to = to;
}

//void ClientHandler::setRemove(QListWidgetItem* remove)
//{
//    this->remove = remove;
//}

void ClientHandler::setPresence(QString status)
{
    this->status = status;
}

void ClientHandler::setOutgoingMessage(QString outgoingMessage)
{
    this->outgoingMessage = outgoingMessage;
}

void ClientHandler::setResult(int result)
{
    this->result = result;
}

void ClientHandler::setClosedBuddyWindow(QString nameOfTheWindow)
{
    this->closedBuddyWindow = nameOfTheWindow;
}

QString ClientHandler::getClosedWindow()
{
    return closedBuddyWindow;
}


QString ClientHandler::getUsername()
{
    return username;
}

QString ClientHandler::getFrom()
{
    return from;
}

QString ClientHandler::getTo()
{
    return to;
}

QString ClientHandler::getEmail()
{
    return email;
}

QString ClientHandler::getIncomingMessage()
{
    return incomingMessage;
}

QString ClientHandler::getPresence()
{
    return status;
}

void ClientHandler::handleIncomingData()
{
    QDataStream incomingData(mySocket);
    incomingData.setVersion(QDataStream::Qt_4_5);
    
    nextBlockSize = 0;
    
    if(nextBlockSize == 0) {
        qDebug() << "nextBlockSize = 0" << endl;
        if(mySocket->bytesAvailable() < sizeof(quint16))
            return;
        incomingData >> nextBlockSize;
    }
    
    if(mySocket->bytesAvailable() < nextBlockSize) {
        qDebug() << "Exiting" << endl;
        return;
    }
    
    qDebug() << "Just received packet from server going to decode it" << endl << flush;
    // call tag reader to see what kind of stream was received
    tagReader(incomingData);
    
    // reset the data stream to get new streams
    incomingData.resetStatus();

    mySocket->flush();
    
}



void ClientHandler::tagReader(QDataStream &theData)
{
    
    theData >> tag;
    
    qDebug() << "the tag: " << tag << endl;
    //    switch (tag)
    //    {
    //        case "authoriziation": getAuthorization(theData); break;
    //        case "registration": registerUser(theData); break;
    //        case "message": getMessage(theData); break;
    //        case "roster": setBuddyList(theData); break;
    //        case "budPresence": setBuddyListStatus(theData); break;
    //        case "addContact": sendAddContact(theData); break;
    //        case "removeContact": sendRemoveContact(theData); break;
    //        default: getMessage(theData); break;
    //    }

    if(QString::compare(tag, authorization, Qt::CaseSensitive)==0)
        getAuthorization(theData);
    
    else if(QString::compare(tag, registration, Qt::CaseSensitive)==0)
        getRegistration(theData);
    
    else if(QString::compare(tag, message, Qt::CaseSensitive)==0)
        getMessage(theData);
    
    else if(QString::compare(tag, groupMessage, Qt::CaseSensitive)==0)
        cout << "groupMessage" << endl;
    
    else if(QString::compare(tag, roster, Qt::CaseSensitive)==0)
        setBuddyList(theData);
    
    else if(QString::compare(tag, budPresence, Qt::CaseSensitive)==0) {
        //counter ++;
        //qDebug() << "this is the number of rosters received so far: " << counter;
        setBuddyListStatus(theData);
    }
    else if(QString::compare(tag, presence, Qt::CaseSensitive)==0)
        cout << "presence" << endl;
    
    else if (QString::compare(tag, addContact, Qt::CaseSensitive)==0)
        cout << "Error Adding Contact" << endl;
    //addContact::errorLabelUpdate();

    else if (QString::compare(tag, removeContact, Qt::CaseSensitive)==0)
        setBuddyList(theData);

    return;
}


void ClientHandler::getAuthorization(QDataStream &theData)
{
    
    theData >> userId;
    
    if(-1!=userId) {
        emit authorizationPassed();
        qDebug() << "user was found id returned" << endl << flush;
    }
    else {
        //         mySocket->disconnectFromHost();
        emit authorizationDenied();
        qDebug() << "user was not found client disconnected" << endl << flush;
    }
    
    return;
}

int ClientHandler::getResult()
{
    return result;
}

void ClientHandler::getRegistration(QDataStream &theData){

    theData >> result;
    qDebug() << result << endl << flush;
    if(result == 1) {
        emit registrationPassed();
    }
    else {
        emit registrationDenied();
    }
    
    return;
    
}

void ClientHandler::getMessage(QDataStream &theData)
{
    
    theData >> from >> to >> incomingMessage;
    qDebug() << from << to << incomingMessage;
    
    emit messageReady();

    return;
}

void ClientHandler::sendAuthorization()
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_5);
    out << quint16(0) << authorization << username << password;
    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));
    mySocket->write(block);
    
    return;
}

void ClientHandler::getBuddies()
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_5);
    out << quint16(0) << roster << username;
    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));
    mySocket->write(block);
    return;
}


void ClientHandler::sendRegistration()
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_5);
    out << quint16(0) << registration << username << password << email;
    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));
    mySocket->write(block);
    return;
}


void ClientHandler::sendMessage()
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_5);
    out << quint16(0) << message << from << to << outgoingMessage;
    //qDebug() << "the message:" << outgoingMessage;
    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));
    qDebug() << mySocket->write(block);
    
    //for(int i=0; i< block.size(); i++)
     //   qDebug() << block.at(i);
    //qDebug() << "\n" ;
    return;
}

//add email to handler
void ClientHandler::sendAddContact()
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_5);
    out << quint16(0) << addContact << username << screenName << email;
    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));
    mySocket->write(block);
    return;
}

void ClientHandler::sendRemoveContact()
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_5);
    out << quint16(0) << removeContact << username << to;
    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));
    mySocket->write(block);
    return;
}



void ClientHandler::sendPresence()
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_5);
    out << quint16(0) << presence << username << status;
    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));
    mySocket->write(block);
    return;
}

void ClientHandler::emitPrintingSignal()
{
    emit messageReadyForDisplaying();
    
}

void ClientHandler::emitClosedWindow()
{
    emit closedWindow();

}

void ClientHandler::setBuddyList(QDataStream &theData)
{
    emit closeAddWindow();
    allMyBuddies.clear();

    QString buds;

    //theData.resetStatus();
    theData >> buds;
    QStringList temp = buds.split(";");

    for(int i = 0; i != temp.size(); i++)
    {
        qDebug() << "GOt : " << temp.at(i);
        allMyBuddies.push_back(temp.at(i));
    }

    qDebug() << "We got the size of: " << allMyBuddies.size();
    // delete before release
    for(int i=0; i<allMyBuddies.size(); i++)
        qDebug() << allMyBuddies.at(i);
    emit rosterReceived();
}

void ClientHandler::setBuddyListStatus(QDataStream &theData)
{
    theData >> allMyBuddiesStatus;
    
    // delete before release
    for(int i=0; i<allMyBuddiesStatus.size(); i++)
        qDebug() << allMyBuddiesStatus.at(i);
    emit statusReceived();
}

